Tutorials on how to use the Folium package

Before starting, make sure the needed packages are installed in your python3 kernel.

If they are not, you can install them from a terminal with pip (or conda):
     $ pip install pandas
     $ pip install numpy
     $ pip install random
     $ pip install folium

First, let's import the needed packages

In [3]:
import pandas as pd
import numpy as np
import random
import folium
from folium import plugins

The DataFrame is from a UCI dataset

The DF consists of all the points (in gps-coordinates) for 163 vehicle trajectories

The columns (from the owner description):

  • id: unique key to identify each point
  • latitude: latitude from where the point is
  • longitude: longitude from where the point is
  • track_id: identify the trajectory which the point belong
  • time: datetime when the point was collected (GMT-3)
In [32]:
df = pd.read_csv("data/go_track_trackspoints.csv")

print('The DataFrame has', len(df), 'gps points, and', len(np.unique(df.track_id)), 'vehicle trajectories')
The DataFrame has 18107 gps points, and 163 vehicle trajectories
In [33]:
# Just a sample of the data:
df.head()
Out[33]:
id latitude longitude track_id time
0 1 -10.939341 -37.062742 1 2014-09-13 07:24:32
1 2 -10.939341 -37.062742 1 2014-09-13 07:24:37
2 3 -10.939324 -37.062765 1 2014-09-13 07:24:42
3 4 -10.939211 -37.062843 1 2014-09-13 07:24:47
4 5 -10.938939 -37.062879 1 2014-09-13 07:24:53

Get the trajectory lenght in minutes

In [34]:
# first transform the time column from sring type to datetime:
df.time = pd.to_datetime(df.time)

# function that returns the length in minutes for a trajectory
def get_traj_lenght(x):
    return float((x.max() - x.min()).total_seconds()/60)

# Add the trajectory-length column using groupby-transform:
df['traj_length'] = df.groupby(['track_id'])['time'].transform(get_traj_lenght)

df.head()
Out[34]:
id latitude longitude track_id time traj_length
0 1 -10.939341 -37.062742 1 2014-09-13 07:24:32 8.266667
1 2 -10.939341 -37.062742 1 2014-09-13 07:24:37 8.266667
2 3 -10.939324 -37.062765 1 2014-09-13 07:24:42 8.266667
3 4 -10.939211 -37.062843 1 2014-09-13 07:24:47 8.266667
4 5 -10.938939 -37.062879 1 2014-09-13 07:24:53 8.266667

Reduced sample

For the purpose of this tutorial, I've reduced the data sample to include only vehicle tracks with track_id < 51

In [35]:
df = df[ df.track_id < 30]

print('The DataFrame has', len(df), 'gps points, and', len(np.unique(df.track_id)), 'vehicle trajectories')
The DataFrame has 3171 gps points, and 23 vehicle trajectories

Visualisation with Folium

Add all the points of the DF to a Folium map

In [36]:
# Create a map centered in the relevant area ()
mymap_1 = folium.Map(location = [ -10.939341, -37.062742], control_scale = True, zoom_start = 14)

# Add all the df points to mymap. 

%time [ folium.CircleMarker(\
        location = [row['latitude'], row['longitude']],\
        radius = 1,\
        color = 'orange',\
        fill = True,\
        fill_color = 'orange' ).add_to(mymap_1) for index, row in df.iterrows() ]

#show map
mymap_1
CPU times: user 573 ms, sys: 16.4 ms, total: 589 ms
Wall time: 593 ms
Out[36]:

Add all the points of the DF to a Folium map coloured by trajectory

In [37]:
# Create a map centered in the relevant area ()
mymap_2 = folium.Map(location = [ -10.939341, -37.062742], control_scale = True, zoom_start = 14)


# Split the DF by trajectories, and plot one at a time:
for tr,tdf in df.groupby('track_id'):
    
    #randomly generate a color for this trajectory:
    tcolor = "#"+''.join([random.choice('0123456789ABCDEF') for j in range(6)])
            
    
    # Add all the tdf points for this trajectory to mymap. 
    [ folium.CircleMarker(\
            location = [row['latitude'], row['longitude']],\
            radius = 1,\
            color = tcolor,\
            fill = True,\
            fill_color = tcolor ).add_to(mymap_2) for index, row in tdf.iterrows() ]

    
#show map
mymap_2
Out[37]:

Create a Folium heatmap

In [38]:
# Create a map centered in the relevant area ()
mymap_3 = folium.Map(location = [ -10.939341, -37.062742 ], control_scale = True, zoom_start = 14)


# Add an heatmap from the df points: instead of points the points-density is displayed
plugins.HeatMap(data = df[['latitude', 'longitude']].values.tolist(), radius=8, max_zoom=14).add_to(mymap_3)

#show map
mymap_3
Out[38]:

Create a layered Folium map

In [39]:
# Create a map centered in the relevant area ()
mymap_4 = folium.Map(location = [ -10.939341, -37.062742 ], control_scale = True, zoom_start = 14)


### First Layer: the heatmap ###

# create layer named "HeatMap"
hm1 = folium.FeatureGroup("HeatMap") 
# add heatmap to layer
hm1.add_child(plugins.HeatMap(df[['latitude', 'longitude']].values.tolist()))
# add layer to map
mymap_4.add_child(hm1)

################################


### Second Layer: with sublayers ###

# create main-layer named "Data Points"
hm2 = folium.FeatureGroup("Data Points") 

# Create Sub-Layer 1 named "Short Rides"
hm_sublayer_1 = plugins.FeatureGroupSubGroup(hm2, "Short Rides")  

# Create Sub-Layer 2 named "Long Rides"
hm_sublayer_2 = plugins.FeatureGroupSubGroup(hm2, "Long Rides")  

# Add to Sub-Layer 1 all points from short rides (trajectories < 60 minutes)
for index, row in df[ df.traj_length <= 60 ].iterrows():
        hm_sublayer_1.add_child(folium.Circle([row['latitude'], row['longitude']], color = 'orange', radius = 6))
        
# Add to Sub-Layer 1 all points from long rides (trajectories > 60 minutes)
for index, row in df[ df.traj_length > 60 ].iterrows():
        hm_sublayer_2.add_child(folium.Circle([row['latitude'], row['longitude']], color = 'green', radius = 6))
        


# add layer to map
mymap_4.add_child(hm2)
# add sub-layer to map
mymap_4.add_child(hm_sublayer_1)
# add sub-layer to map
mymap_4.add_child(hm_sublayer_2)

################################


# Add LayerControl to show/hide each layer
folium.LayerControl().add_to(mymap_4)


#show map
mymap_4
Out[39]:

Create an animated Folium map

Prepare the data

In [40]:
# Select one trajectory to map and sort the df by time:
subset = df [ df.track_id == 1 ].sort_values('time')

#Create a list of lists where each inner elements are the points to plot, 
#      the outer ones are the time order in which to plot 

data_split = [ [ point ] for point in subset[['latitude', 'longitude']].values.tolist() ]

Add the split data to the map to create an animated map

In [41]:
# Create a map centered in the relevant area ()
animap = folium.Map(location = [ -10.939341, -37.062742 ], control_scale = True, zoom_start = 14)

# Add cluster data
hm = plugins.HeatMapWithTime(data = data_split, auto_play = True, radius = 30).add_to(animap)

# Punti di interesse
fg = folium.FeatureGroup("Animated Map") 

animap.add_child(fg)
Out[41]: